package everyday;

import entity.Teacher;
import org.junit.jupiter.api.Test;

import java.lang.reflect.Field;

/**
 * 反射相关操作
 *
 * @author gaojie
 * @date 2023-04-07
 */
public class ReflectOperation {

    /**
     * 测试获取class的父类，直到Object
     */
    @Test
    void test01() {
        final Field[] declaredFields = Teacher.class.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField.getName());
        }

        final Class<? super Teacher> superclass = Teacher.class.getSuperclass();
        System.out.println(superclass);
        System.out.println(superclass.getSuperclass());
        System.out.println(superclass.getSuperclass().getSuperclass());
        System.out.println(superclass.getSuperclass().getSuperclass().equals(Object.class));
        for (Field declaredField : superclass.getDeclaredFields()) {
            System.out.println(declaredField.getName());
        }
    }

    /**
     * 测试根据属性名获取属性：看属性不存在时是否会报错
     * 结论：会直接抛异常
     */
    @Test
    void test02() throws NoSuchFieldException {
        Teacher.class.getDeclaredField("age");
    }

    /**
     * 测试查找类属性，不存在时从父类查找，直到Object
     * 测试结果：方法功能正常，能够找到
     */
    @Test
    void test03() {
        final Field age = getDeclaredField(Teacher.class, "age");
        System.out.println(age);
        final Field desc = getDeclaredField(Teacher.class, "desc");
        System.out.println(desc);
        final Field name = getDeclaredField(Teacher.class, "name");
        System.out.println(name);
        final Field id = getDeclaredField(Teacher.class, "id");
        System.out.println(id);
    }

    /**
     * 根据属性名获取类的属性，支持查找父类，找到为止
     *
     * @param clazz     类对象
     * @param fieldName 属性名
     */
    private Field getDeclaredField(Class<?> clazz, String fieldName) {
        if (Object.class.equals(clazz)) {
            System.err.println("属性不存在");
            return null;
        }
        try {
            return clazz.getDeclaredField(fieldName);
        } catch (NoSuchFieldException e) {
            return getDeclaredField(clazz.getSuperclass(), fieldName);
        }
    }
}